/**
 * Copyright(c) 2013 Jade Techonologies Co., Ltd.
 *
 * History:
 *   13-4-23 下午10:05 Created by dwzhang
 */
package com.jade.framework.base.criterion.sql;

import java.util.List;

import com.jade.framework.base.criterion.*;

/**
 * 把Criteria解析成相应的SQL语句。
 *
 * @author dwzhang
 * @version 1.0 13-4-23 下午10:05
 */
public class CriteriaInterpreter implements CriterionInterpreter<SqlContext, Criteria>
{
    /**
     * 对表达式进行解析，形成可以用于实际查询的上下文。
     *
     * @param context  解析上下文。
     * @param criteria 需要解析的对象，包括表达式、Order等等。
     */
    public void interprete(SqlContext context, Criteria criteria)
    {
        List<Criterion> criterions = criteria.getCriterions();
        List<Order> orders = criteria.getOrders();
        List<QueryEntity> entities = criteria.getEntities();
        Group group = criteria.getGroup();
        Having having = criteria.getHaving();
        //String additionalCondition = criteria.getAdditionalCondition();

        intercepteEntities(context, entities);

        intercepteCriterions(context, criterions);

        //        if (StringUtil.isValid(additionalCondition)) {
        //            if (!criterions.isEmpty()) {
        //                context.append(" AND ");
        //            }
        //            context.append(additionalCondition);
        //        }

        intercepteGroup(context, group);

        intercepteHaving(context, having);

        intercepteDistinct(context, criteria.isDistinct());

        intercepteOrders(context, orders);
    }

    /**
     * 解析条件.
     *
     * @param context    上下文
     * @param criterions 条件集合
     */
    protected void intercepteCriterions(SqlContext context, List<Criterion> criterions)
    {
        SqlUtils.interpreteSql(context, criterions);
        /*
        String upperSql = context.getContextString().toUpperCase();
        int index = upperSql.indexOf(Constants.WHERE);
        for (int i = 0; i < criterions.size(); i++) {
            if (i == 0 && index > 0) {
                if (index + Constants.WHERE.length() + 4 < upperSql.length()) {
                    //Need add AND
                    assembleContext(context, Constants.AND);
                }
            }
            else if (i > 0) {
                assembleContext(context, Constants.AND);
            }
            SqlUtils.interprete(context, criterions.get(i));
        }
        */
    }

    /**
     * 解析Entity.
     *
     * @param context  上下文
     * @param entities Entity集合
     */
    protected void intercepteEntities(SqlContext context, List<QueryEntity> entities)
    {
        for (QueryEntity entity : entities) {
            SqlUtils.interprete(context, entity);
        }
    }

    /**
     * 解析排序.
     *
     * @param context 上下文
     * @param orders  排序集合
     */
    protected void intercepteOrders(SqlContext context, List<Order> orders)
    {
        if (!orders.isEmpty()) {
            assembleContext(context, Constants.ORDER_BY);
        }

        for (int i = 0; i < orders.size(); i++) {
            if (i > 0) {
                context.append(Constants.COMMA);
            }
            SqlUtils.interprete(context, orders.get(i));
        }
    }

    /**
     * 解析Having语句.
     *
     * @param context 上下文
     * @param having  having对象集合
     */
    protected void intercepteHaving(SqlContext context, Having having)
    {
        if (having != null) {
            SqlUtils.interprete(context, having);
        }
    }

    /**
     * 解析Group By.
     *
     * @param context 上下文
     * @param group   group by对象集合
     */
    protected void intercepteGroup(SqlContext context, Group group)
    {
        if (group != null) {
            SqlUtils.interprete(context, group);
        }
    }

    /**
     * 解析Group By.
     *
     * @param context  上下文
     * @param distinct distinct属性
     */
    protected void intercepteDistinct(SqlContext context, boolean distinct)
    {
        if (!distinct) {
            return;
        }
        SqlUtils.interprete(context, distinct);
    }

    /**
     * 一种[" "+$+" "]的组装方法.
     *
     * @param context 上下文
     * @param middle  中间的字符串
     */
    protected void assembleContext(SqlContext context, String middle)
    {
        context.append(Constants.BLANK);
        context.append(middle);
        context.append(Constants.BLANK);
    }
}
